/*
*  Copyright 2019-2020 Zheng Jie
*
*  Licensed under the Apache License, Version 2.0 (the "License");
*  you may not use this file except in compliance with the License.
*  You may obtain a copy of the License at
*
*  http://www.apache.org/licenses/LICENSE-2.0
*
*  Unless required by applicable law or agreed to in writing, software
*  distributed under the License is distributed on an "AS IS" BASIS,
*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*  See the License for the specific language governing permissions and
*  limitations under the License.
*/
package me.zhengjie.modules.system.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.google.common.collect.Lists;
import me.zhengjie.modules.system.domain.Atmr;
import me.zhengjie.modules.system.domain.ExamDatabase;
import me.zhengjie.modules.system.repository.ExamDatabaseRepository;
import me.zhengjie.modules.system.repository.ExamOrderRepository;
import me.zhengjie.modules.system.service.dto.ExamDatabaseQueryCriteria;
import me.zhengjie.utils.ValidationUtil;
import me.zhengjie.utils.FileUtil;
import lombok.RequiredArgsConstructor;
import me.zhengjie.modules.system.repository.AtmrRepository;
import me.zhengjie.modules.system.service.AtmrService;
import me.zhengjie.modules.system.service.dto.AtmrDto;
import me.zhengjie.modules.system.service.dto.AtmrQueryCriteria;
import me.zhengjie.modules.system.service.mapstruct.AtmrMapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import me.zhengjie.utils.PageUtil;
import me.zhengjie.utils.QueryHelp;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.*;
import java.io.IOException;
import java.util.stream.Collectors;
import javax.servlet.http.HttpServletResponse;

/**
* @website https://el-admin.vip
* @description 服务实现
* @author zhaoxiancheng
* @date 2021-11-18
**/
@Service
@RequiredArgsConstructor
public class AtmrServiceImpl implements AtmrService {

    private final AtmrRepository atmrRepository;
    private final AtmrMapper atmrMapper;

    private final ExamOrderRepository examOrderRepository;

    private final ExamDatabaseRepository examDatabaseRepository;

    @Override
    public Map<String,Object> queryAll(AtmrQueryCriteria criteria, Pageable pageable){
        Page<Atmr> page = atmrRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder),pageable);
        Page<AtmrDto> dtpPage =  page.map(atmrMapper::toDto);
        if(dtpPage.getTotalElements() <= 0){
            return PageUtil.toPage(dtpPage);
        }
        Iterator<Atmr> iterator = page.iterator();
        List<String> atmrIdList = Lists.newArrayList();
        while (iterator.hasNext()){
            atmrIdList.add(String.valueOf(iterator.next().getId()));
        }
        Map<Long,Object[]> result = queryCount(atmrIdList);


        if(dtpPage.getTotalElements() <= 0){
            return PageUtil.toPage(dtpPage);
        }
        setExamDatabaseName(dtpPage);
        Iterator<AtmrDto> iteratorDto = dtpPage.iterator();
        while (iteratorDto.hasNext()){
            AtmrDto atmrDto = iteratorDto.next();
            Object[] attr = result.get(atmrDto.getId());
            if(ObjectUtil.isEmpty(attr)){
                atmrDto.setExamOrderNumber(0);
                atmrDto.setExamOrderAmount(BigDecimal.ZERO);
            } else {
                atmrDto.setExamOrderNumber(Integer.valueOf(attr[1].toString()));
                atmrDto.setExamOrderAmount(new BigDecimal(String.valueOf(attr[2])));
            }
        }

        return PageUtil.toPage(dtpPage);
    }

    /**
     * 统计测评情况
     * @param atmrIdList
     * @return
     */
    private Map<Long,Object[]> queryCount(List<String> atmrIdList){
        if(CollectionUtils.isEmpty(atmrIdList)){
            return new HashMap<>();
        }
        List<Object[]> statistics = examOrderRepository.statisticsExam(atmrIdList.toArray(new String[]{}));
        if(CollectionUtils.isEmpty(statistics)){
            return new HashMap<>();
        }
        Map<Long,Object[]> result = new HashMap<>();
        for(Object[] v : statistics){
            result.put(Long.valueOf(v[0].toString()),v);
        }
        return result;
    }

    /**
     * 查询题库名称
     * @param dtpPage
     */
    private void setExamDatabaseName(Page<AtmrDto> dtpPage){
        if(dtpPage.getTotalElements() <= 0){
            return;
        }
        List<AtmrDto> list = dtpPage.getContent();
        Set<Long> examDatabaseIdSet = list.stream().map(AtmrDto :: getExamDatabaseId).collect(Collectors.toSet());
        if(CollectionUtils.isEmpty(examDatabaseIdSet)){
            return;
        }
        ExamDatabaseQueryCriteria queryCriteria = new ExamDatabaseQueryCriteria();
        queryCriteria.setDatabaseIdSet(examDatabaseIdSet);
        List<ExamDatabase> databaseList = examDatabaseRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,queryCriteria,criteriaBuilder));
        if(CollectionUtils.isEmpty(databaseList)){
            return;
        }
        final Map<Long,String> databaseNameMap = databaseList.stream().collect(Collectors.toMap(ExamDatabase::getDatabaseId,ExamDatabase::getDatabaseName));
        list.forEach(s -> {
            s.setExamDatabaseName(databaseNameMap.get(s.getExamDatabaseId()));
        });
    }

    @Override
    public List<AtmrDto> queryAll(AtmrQueryCriteria criteria){
        return atmrMapper.toDto(atmrRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder)));
    }

    @Override
    @Transactional
    public AtmrDto findById(Integer id) {
        Atmr atmr = atmrRepository.findById(id).orElseGet(Atmr::new);
        if (null == atmr || atmr.getId() == null){
            return null;
        }
        ValidationUtil.isNull(atmr.getId(),"Atmr","id",id);
        return atmrMapper.toDto(atmr);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public AtmrDto create(Atmr resources) {
        return atmrMapper.toDto(atmrRepository.save(resources));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(Atmr resources) {
        Atmr atmr = atmrRepository.findById(resources.getId()).orElseGet(Atmr::new);
        ValidationUtil.isNull( atmr.getId(),"Atmr","id",resources.getId());
        atmr.copy(resources);
        atmrRepository.save(atmr);
    }

    @Override
    public void deleteAll(Integer[] ids) {
        for (Integer id : ids) {
            atmrRepository.deleteById(id);
        }
    }

    @Override
    public void download(List<AtmrDto> all, HttpServletResponse response) throws IOException {
        List<Map<String, Object>> list = new ArrayList<>();
        for (AtmrDto atmr : all) {
            Map<String,Object> map = new LinkedHashMap<>();
            map.put("测试名称", atmr.getAtmrName());
            map.put("测试类型", atmr.getAtmrType());
            map.put("测试说明", atmr.getAtmrDesc());
            map.put("备注", atmr.getRemark());
            map.put("测试价格", atmr.getPrice());
            map.put("是否启用：0-启用；1-停用", atmr.getStatus());
            map.put("总题数", atmr.getExamCount());
            map.put("测试报告费用", atmr.getReportPrice());
            list.add(map);
        }
        FileUtil.downloadExcel(list, response);
    }
}